﻿Public Class ClsMultColumnComboBox
    Inherits ComboBox

    Private m_ColumnWidths As String '栏目宽度字串：100;150;200等
    Private m_ColumnTitles As String '栏目标题字串：Name;Code;Sexy等
    Private m_ColumnNames As String '栏目成员名称：Name;Code;Sexy等,如果是类，则是类中属性，如果是table，则是字段名称
    Private m_ColumnIndexs As String '栏目成员所在索引IList接口实现；如0;1;3等
    Private m_SelectedValue2 As Object '所选行的第二个返回值。由第二个返回索引指定,此属性和下面属性配合使用，在EditingControl的selectedItem中赋值
    Private m_SelectedIndex2 As Int32 '所选行的第二个返回值索引。

    Public Sub New()
        MyBase.New()

        m_SelectedIndex2 = -1
        Me.DrawMode = DrawMode.OwnerDrawFixed
    End Sub


    <System.ComponentModel.Browsable(True), System.ComponentModel.Description("各栏的宽度值，以分号分隔。")>
    Public Property ColumnWidths As String
        Get
            Return m_ColumnWidths
        End Get
        Set(value As String)
            m_ColumnWidths = value
        End Set
    End Property

    <System.ComponentModel.Browsable(True), System.ComponentModel.Description("各栏的标题，以分号分隔。")>
    Public Property ColumnTitles As String
        Get
            Return m_ColumnTitles
        End Get
        Set(value As String)
            m_ColumnTitles = value
        End Set
    End Property

    Public Property ColumnNames As String
        Get
            Return m_ColumnNames
        End Get
        Set(value As String)
            m_ColumnNames = value
        End Set
    End Property

    Public Property ColumnIndexs As String
        Get
            Return m_ColumnIndexs
        End Get
        Set(value As String)
            m_ColumnIndexs = value
        End Set
    End Property

    Public Property SelectedValue2 As Object
        Get
            Return m_SelectedValue2
        End Get
        Set(value As Object)
            m_SelectedValue2 = value
        End Set
    End Property

    Public Property SelectedIndex2 As Integer
        Get
            Return m_SelectedIndex2
        End Get
        Set(value As Integer)
            m_SelectedIndex2 = value
        End Set
    End Property

    Protected Overrides Sub OnSelectedIndexChanged(e As EventArgs)
        MyBase.OnSelectedIndexChanged(e)

        Try
            'Dim col As DataGridViewMultiColumnComboBoxColumn = CType(m_OwnerCell.OwningColumn, DataGridViewMultiColumnComboBoxColumn)
            '判断是否设置了第二返回值 
            If Me.SelectedIndex2 <> -1 Then
                Me.SelectedValue2 = Me.Items(Me.SelectedIndex)(Me.SelectedIndex2)
            End If

            'Debug.Print("OnselectedIndexchanged - selectedindex2" & col.Items(Me.SelectedIndex)(col.SelectedIndex2))
        Catch ex As Exception


        End Try
    End Sub

    Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
        Select Case keyData
            Case Keys.Enter
                '判断当前是否已经下拉
                If Me.DroppedDown Then
                    'Me.DroppedDown = False
                    SendKeys.Send("{Tab}")
                Else
                    Me.DroppedDown = True
                End If
                Return True
        End Select
        '一定要保留父级处理
        Return MyBase.ProcessCmdKey(msg, keyData)
    End Function

    Protected Overrides Sub OnDrawItem(e As DrawItemEventArgs)
        MyBase.OnDrawItem(e)

        '准备画控件
        '当前控件的 客户区
        Dim rec As Rectangle = e.Bounds
        '设置分隔线的笔刷
        Dim NormalTextBrush As SolidBrush = New SolidBrush(SystemColors.ControlText)


        '取出当前控件所在栏
        'Dim ownerColumn As DataGridViewMultiColumnComboBoxColumn = CType(OwnerCell.OwningColumn, DataGridViewMultiColumnComboBoxColumn)
        '取出各栏宽度
        Dim colWidths() As String = Nothing

        If Me.ColumnWidths IsNot Nothing Then
            colWidths = Me.ColumnWidths.Split(";"c)
        End If

        '如果有数据，即e.index有正常值
        If e.Index = -1 Then
            Return '没有数据需要画
        End If

        '取出当前列的数据源
        'Dim colDataSource As Object = ownerColumn.DataSource
        Dim colItems As Object = Me.Items
        Dim curDataView As DataRowView
        Dim currentRow As DataRow = Nothing
        Dim currentItems() As Object
        '取当前行，试着转换为datatable对象
        curDataView = TryCast(Items(e.Index), DataRowView)
        If curDataView IsNot Nothing Then
            currentRow = curDataView.Row
        End If

        If currentRow Is Nothing Then
            Dim iL As IList = CType(Items(e.Index), IList)
            ReDim currentItems(iL.Count - 1)
            For i = 0 To iL.Count - 1
                currentItems(i) = iL.Item(i)
            Next
        Else
            currentItems = currentRow.ItemArray
        End If

        '判断行是否有集合值
        If currentItems Is Nothing Then
            Return

        End If
        '开始画
        '取当前值
        Dim currentText As String = GetItemText(Items(e.Index))

        'Debug.Print("OnDrawItem:currentText=" & currentText)

        '先画普通白色背景
        Dim normalBackBrush As SolidBrush = New SolidBrush(Color.White)
        e.Graphics.FillRectangle(normalBackBrush, rec)

        '判断是否下拉
        If Me.DroppedDown And (Not Margin.Top = rec.Top) Then
            '有下拉，则画显示部分

            '当前偏移
            Dim currentOffset As Integer = rec.Left
            '高亮画刷
            Dim highLightBackBrush As SolidBrush = New SolidBrush(SystemColors.Highlight)
            If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
                '被选中背景颜色 
                e.Graphics.FillRectangle(highLightBackBrush, rec)
            End If

            Dim addBorder As Boolean = False
            Dim valueItem As Object

            'For Each rowItem In currentItems
            For i = 0 To currentItems.Length - 1
                valueItem = currentItems(i)
                Dim value As String = currentItems(i).ToString() 'TODO:应该支持多种数据类型

                'Debug.Print("value=" & value)

                If addBorder Then
                    '画分隔
                    Dim gridBrush As SolidBrush = New SolidBrush(Color.Gray)
                    Dim linesNum As Long = 1 '可以考虑配置
                    While linesNum > 0
                        linesNum -= 1
                        Dim first As Point = New Point(rec.Left + currentOffset, rec.Top)
                        Dim last As Point = New Point(rec.Left + currentOffset, rec.Bottom)
                        e.Graphics.DrawLine(New Pen(gridBrush), first, last)

                        currentOffset += 1
                    End While
                Else
                    addBorder = True
                End If

                '测量宽度
                Dim extent As SizeF = e.Graphics.MeasureString(valueItem, e.Font)
                Dim Width As Decimal = CType(extent.Width, Decimal)
                '如果 太长，则截断
                Dim textRec As Rectangle = New Rectangle(currentOffset, rec.Y, CType(Decimal.Ceiling(Width), Integer), rec.Height)
                '取出当前列设定宽度值，如果未设定，则宽度默认为50
                Dim fixedWidth As Int32
                If String.IsNullOrEmpty(Me.ColumnWidths) OrElse colWidths.Length < 1 Then
                    fixedWidth = 50
                Else
                    fixedWidth = Integer.Parse(colWidths(i))

                End If
                '开始画 一个值 
                If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
                    '被选择的部分
                    Dim HighlightedText As SolidBrush = New SolidBrush(SystemColors.HighlightText)
                    '如果前面部分太长，则重画应当被截断的部分背景
                    e.Graphics.FillRectangle(highLightBackBrush, currentOffset, rec.Y, fixedWidth, extent.Height) '此处应根据设置进行宽度修改
                    '画字串
                    e.Graphics.DrawString(value, e.Font, normalBackBrush, textRec)
                Else
                    '如果前面部分太长，则重画应当被截断的部分背景
                    e.Graphics.FillRectangle(normalBackBrush, currentOffset, rec.Y, fixedWidth, extent.Height) '此处应根据设置进行宽度修改
                    '画字串
                    e.Graphics.DrawString(value, e.Font, NormalTextBrush, textRec)
                End If

                currentOffset += fixedWidth  'fixedAlignColumnSize 设置

            Next
        Else
            '没有下拉，只画当前值
            e.Graphics.DrawString(currentText, e.Font, NormalTextBrush, rec)
        End If
    End Sub
End Class
